//package com.tiancheng.trade.payment.task.ums;
//
//import com.jcraft.jsch.ChannelSftp;
//import com.jcraft.jsch.JSchException;
//import com.jcraft.jsch.Session;
//import com.tiancheng.trade.commom.utils.ServiceLocator;
//import com.tiancheng.trade.payment.channel.ums.utils.UmsUtil;
//import com.tiancheng.trade.payment.configuration.UmsAllConfigs;
//import com.tiancheng.trade.payment.feign.FileUpload;
//import com.tiancheng.trade.payment.feign.dto.FilerUploadResult;
//import com.tiancheng.trade.payment.task.ums.bo.DownloadFileBo;
//import com.tiancheng.trade.payment.task.ums.bo.FileRetBo;
//import com.tiancheng.trade.payment.util.SftpUtil;
//import com.tiancheng.trade.payment.util.TxtUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.fileupload.FileItem;
//import org.apache.commons.fileupload.FileItemFactory;
//import org.apache.commons.fileupload.disk.DiskFileItemFactory;
//import org.springframework.http.MediaType;
//import org.springframework.util.CollectionUtils;
//import org.springframework.util.StringUtils;
//
//import javax.security.cert.X509Certificate;
//import java.io.*;
//import java.security.PrivateKey;
//import java.security.PublicKey;
//import java.time.LocalDateTime;
//import java.time.ZoneOffset;
//import java.time.format.DateTimeFormatter;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Set;
//import java.util.stream.Collectors;
//
//import static com.tiancheng.trade.payment.util.SftpUtil.*;
//
///**
// * 银联商务相关文件操作实现
// *
// * @author kellen
// * @date 2024/11/9
// */
//@Slf4j
//public class UmsFileHandler {
//    private static final UmsAllConfigs UMS_PROPERTIES = ServiceLocator.getBean(UmsAllConfigs.class);
//    private static PrivateKey batchPrivateKey = null;
//    private static PublicKey countPubKey = null;
//    /**
//     * 如超出请拆分至多个文件，上传批次至少间隔20分钟
//     */
//    private static final long CYCLE_TIME = 25 * 60 * 1000;
//
//    static {
//        try {
//            File rsaPrivateFile = new File(UMS_PROPERTIES.getRsaPrivatePath());
//            batchPrivateKey = UmsUtil.getPriKeyPkcs12(new FileInputStream(rsaPrivateFile), UMS_PROPERTIES.getRsaPrivatePassword());
//            File rsaPublicFile = new File(UMS_PROPERTIES.getRsaPublicPath());
//            InputStream countPubKeyStoreFileStream = new FileInputStream(rsaPublicFile);
//            X509Certificate countCert = X509Certificate.getInstance(countPubKeyStoreFileStream);
//            countPubKey = countCert.getPublicKey();
//        } catch (Exception e) {
//            log.error("{}初始化失败{}", UmsFileHandler.class.getName(), e);
//        }
//    }
//
//    /**
//     * 获取银联商务分账、划付文件服务器sftp连接
//     *
//     * @return ChannelSftp
//     * @throws Exception
//     */
//    public static ChannelSftp getUmsSettleSftp() throws Exception {
//        // 尝试先连接服务器1，失败则连接服务器2
//        try {
//            return (ChannelSftp) getChannel(null, UMS_PROPERTIES.getUmsSettleUser(),
//                    UMS_PROPERTIES.getUmsSettlePassword(), UMS_PROPERTIES.getUmsSettleHost1(),
//                    UMS_PROPERTIES.getUmsSettlePort1(), SftpUtil.HOST_KEY_CHECKING_NO,
//                    SftpUtil.CON_MODE_SFTP);
//        } catch (Exception ignored) {
//        }
//
//        return (ChannelSftp) getChannel(null, UMS_PROPERTIES.getUmsSettleUser(),
//                UMS_PROPERTIES.getUmsSettlePassword(), UMS_PROPERTIES.getUmsSettleHost2(),
//                UMS_PROPERTIES.getUmsSettlePort2(), SftpUtil.HOST_KEY_CHECKING_NO,
//                SftpUtil.CON_MODE_SFTP);
//    }
//
//    /**
//     * 上传文件到服务器目标目录
//     *
//     * @param path      目标目录
//     * @param apprFiles 划付文件
//     * @param distFiles 分账文件
//     */
//    public static void parallelUploadFile(String path, List<File> apprFiles, List<File> distFiles) {
//        int times = Math.max(apprFiles.size(), distFiles.size());
//        for (int i = 0; i < times; i++) {
//            if (i < apprFiles.size()) {
//                uploadFile(path, apprFiles.get(i));
//            }
//            if (i < distFiles.size()) {
//                uploadFile(path, distFiles.get(i));
//            }
//            if (i == (times - 1)) {
//                break;
//            }
//            try {
//                Thread.sleep(CYCLE_TIME);
//            } catch (InterruptedException ignored) {
//            }
//        }
//    }
//
//    /**
//     * 上传文件到服务器目标目录
//     *
//     * @param path 目标目录
//     * @param file 文件
//     * @return boolean
//     */
//    public static boolean uploadFile(String path, File file) {
//        ChannelSftp sftp = null;
//        File chkFile = null;
//        try {
//            // 生成签名文件
//            String md5 = UmsUtil.getFileMD5String(file);
//            // 签名
//            byte[] signB = UmsUtil.sign(md5.getBytes(), batchPrivateKey, UmsUtil.ALGORITHM_SHA256WITHRSA);
//            chkFile = new File(file.getName() + ".chk");
//            BufferedWriter bwChk = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(chkFile)));
//            bwChk.write(UmsUtil.byteArr2HexString(signB) + "\r\n");
//            bwChk.flush();
//            bwChk.close();
//            sftp = getUmsSettleSftp();
//            // 上传文件
//            upload(path, sftp, SftpUtil.PATH_VALID_775, chkFile, file);
//
//            return true;
//        } catch (Exception e) {
//            log.error("银联商务清分文件 " + file.getName() + " 上传异常: " + e);
//            return false;
//        } finally {
//            if (sftp != null && sftp.isConnected()) {
//                try {
//                    Session Session = sftp.getSession();
//                    Session.disconnect();
//                } catch (JSchException e) {
//                    log.error("upload disconnect error: " + e);
//                }
//                sftp.disconnect();
//            }
//        }
//    }
//
//    /**
//     * 下载目标文件到目标服务器目标目录，并返回文件名信息
//     *
//     * @param settleDate 时间起始点
//     * @param targetPath 源文件目录
//     * @return {@link Set}
//     */
//    public static List<DownloadFileBo> downloadFile(LocalDateTime settleDate, String targetPath, FileUpload fileUpload) {
//        List<DownloadFileBo> lastUpdateFilePaths = new ArrayList<>(); // 文件名信息
//        ChannelSftp sftp = null;
//        try {
//            // 打开通道
//            sftp = getUmsSettleSftp();
//            // 获取源文件目录下所有子文件夹
//            List<ChannelSftp.LsEntry> dirs = SftpUtil.getDirs(targetPath, sftp);
//            if (CollectionUtils.isEmpty(dirs)) {
//                log.info("目录：{} 下没有文件", targetPath);
//                return lastUpdateFilePaths;
//            }
//
//            // 筛选前2天2点后到前1天2点之间发生变动的文件
//            for (ChannelSftp.LsEntry dir : dirs) {
//                // 比较目录最后更新时间是否在时间起始点之后
////                log.info("日期比对结果：{}，{}",getLocalDateTime(dir.getAttrs().getMtimeString()).isAfter(settleDate.minusDays(2)),getLocalDateTime(dir.getAttrs().getMtimeString()).isBefore(settleDate));
//                if (dir.getFilename().startsWith("20") && dir.getAttrs().getMTime() >= settleDate.minusDays(1).toEpochSecond(ZoneOffset.of("+8")) && dir.getAttrs().getMTime() <= settleDate.toEpochSecond(ZoneOffset.of("+8"))) {
//                    log.info("遍历目录，目录：{},修改时间：{}", dir.getFilename(), dir.getAttrs().getMTime());
//                    String filePath = targetPath + dir.getFilename();
//                    List<ChannelSftp.LsEntry> files = getFilesByDir(filePath, sftp);
//                    if (CollectionUtils.isEmpty(files)) {
//                        log.info("该目录下没有文件，目录：{}", filePath);
//                        continue;
//                    }
//                    // 筛选最后修改时间在前2天2点（包含）到前1天2点（不包含）之间的文件
//                    for (ChannelSftp.LsEntry file : files) {
//                        if ((file.getFilename().startsWith("final_02") || file.getFilename().startsWith("final_04")) && file.getAttrs().getMTime() <= settleDate.toEpochSecond(ZoneOffset.of("+8")) &&
//                                file.getAttrs().getMTime() >= settleDate.minusDays(1).toEpochSecond(ZoneOffset.of("+8"))) {
//                            if (!file.getFilename().endsWith(".txt.ret")) {
//                                continue;
//                            }
//                            List<ChannelSftp.LsEntry> collect = files.stream().filter(lsEntry -> lsEntry.getFilename().startsWith(file.getFilename() + ".chk")).collect(Collectors.toList());
//                            if (CollectionUtils.isEmpty(collect)) {
//                                continue;
//                            }
//                            log.info("取到回盘文件，文件名称：{}", file.getFilename());
//                            ChannelSftp.LsEntry chkFile = collect.get(0);
//
//                            InputStream inputStream = sftp.get(filePath + "/" + file.getFilename());
//                            InputStream chkFileInputStream = sftp.get(filePath + "/" + chkFile.getFilename());
//                            // 回盘文件的MD5串
//
//                            ByteArrayOutputStream byteArrayOutputStream = UmsUtil.cloneInputStream(inputStream);
//
//                            InputStream retInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
//                            String retMD5Str = UmsUtil.getFileInputStreamMD5String(retInputStream);
//                            BufferedReader reader = new BufferedReader(new InputStreamReader(chkFileInputStream));
//                            String chkMD5Str = reader.readLine();
//                            if (!UmsUtil.verify(retMD5Str.getBytes("UTF-8"), UmsUtil.hexString2ByteArr(chkMD5Str), countPubKey)) {
//                                log.error("回盘文件校验异常，ret文件md5：{}，chk文件md5：{}", retMD5Str, chkMD5Str);
//                                continue;
//                            }
//                            log.info("回盘文件校验通过！chk文件：{}", chkFile.getFilename());
//                            // 将文件上传的远程服务器
//                            InputStream readInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
//
//                            Object[][] dataFromInputStream = TxtUtil.getDataFromInputStream(readInputStream, "UTF-8");
//                            FilerUploadResult filerUploadResult = uploadFile2Cos(file.getFilename(), readInputStream, fileUpload);
//                            lastUpdateFilePaths.add(new DownloadFileBo(dataFromInputStream, file.getFilename(), filerUploadResult));
//
//                            inputStream.close();
//                            chkFileInputStream.close();
//                            byteArrayOutputStream.close();
//                            retInputStream.close();
//                            readInputStream.close();
//                        }
//                    }
//                }
//            }
//            if (CollectionUtils.isEmpty(lastUpdateFilePaths)) {
//                log.info("未查询到需要处理的回盘文件，日期：{}", settleDate.format(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss")));
//                return lastUpdateFilePaths;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.error("下载回盘文件异常：{}", e.getMessage());
//        } finally {
//            if (sftp != null && sftp.isConnected()) {
//                try {
//                    Session Session = sftp.getSession();
//                    Session.disconnect();
//                } catch (JSchException e) {
//                    log.error("download disconnect error: " + e);
//                }
//                sftp.disconnect();
//            }
//        }
//        return lastUpdateFilePaths;
//    }
//
//
//    /**
//     * 下载目标文件到目标服务器目标目录，并返回文件名信息
//     *
//     * @param settleDate 时间起始点
//     * @param targetPath 源文件目录
//     * @return {@link Set}
//     */
//    public static List<DownloadFileBo> downloadCouponFile(LocalDateTime settleDate, String targetPath, FileUpload fileUpload) {
//        List<DownloadFileBo> lastUpdateFilePaths = new ArrayList<>(); // 文件名信息
//        ChannelSftp sftp = null;
//        try {
//            // 打开通道
//            sftp = getUmsSettleSftp();
//            // 获取源文件目录下所有子文件夹
//            List<ChannelSftp.LsEntry> dirs = SftpUtil.getDirs(targetPath, sftp);
//            if (CollectionUtils.isEmpty(dirs)) {
//                log.info("目录：{} 下没有文件", targetPath);
//                return lastUpdateFilePaths;
//            }
//
//            // 筛选前2天2点后到前1天2点之间发生变动的文件
//            for (ChannelSftp.LsEntry dir : dirs) {
//                // 比较目录最后更新时间是否在时间起始点之后
////                log.info("日期比对结果：{}，{}",getLocalDateTime(dir.getAttrs().getMtimeString()).isAfter(settleDate.minusDays(2)),getLocalDateTime(dir.getAttrs().getMtimeString()).isBefore(settleDate));
//                if (dir.getFilename().startsWith("20") && dir.getAttrs().getMTime() >= settleDate.minusDays(1).toEpochSecond(ZoneOffset.of("+8")) && dir.getAttrs().getMTime() <= settleDate.toEpochSecond(ZoneOffset.of("+8"))) {
//                    log.info("遍历目录，目录：{},修改时间：{}", dir.getFilename(), dir.getAttrs().getMTime());
//                    String filePath = targetPath + dir.getFilename();
//                    List<ChannelSftp.LsEntry> files = getFilesByDir(filePath, sftp);
//                    if (CollectionUtils.isEmpty(files)) {
//                        log.info("该目录下没有文件，目录：{}", filePath);
//                        continue;
//                    }
//                    // 筛选最后修改时间在前2天2点（包含）到前1天2点（不包含）之间的文件
//                    for (ChannelSftp.LsEntry file : files) {
//                        if (file.getFilename().startsWith("09_") && file.getAttrs().getMTime() <= settleDate.toEpochSecond(ZoneOffset.of("+8")) &&
//                                file.getAttrs().getMTime() >= settleDate.minusDays(1).toEpochSecond(ZoneOffset.of("+8"))) {
//                            if (!file.getFilename().endsWith(".txt.ret")) {
//                                continue;
//                            }
//                            List<ChannelSftp.LsEntry> collect = files.stream().filter(lsEntry -> lsEntry.getFilename().startsWith(file.getFilename() + ".chk")).collect(Collectors.toList());
//                            if (CollectionUtils.isEmpty(collect)) {
//                                continue;
//                            }
//                            log.info("取到回盘文件，文件名称：{}", file.getFilename());
//                            ChannelSftp.LsEntry chkFile = collect.get(0);
//
//                            InputStream inputStream = sftp.get(filePath + "/" + file.getFilename());
//                            InputStream chkFileInputStream = sftp.get(filePath + "/" + chkFile.getFilename());
//                            // 回盘文件的MD5串
//
//                            ByteArrayOutputStream byteArrayOutputStream = UmsUtil.cloneInputStream(inputStream);
//
//                            InputStream retInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
//                            String retMD5Str = UmsUtil.getFileInputStreamMD5String(retInputStream);
//                            BufferedReader reader = new BufferedReader(new InputStreamReader(chkFileInputStream));
//                            String chkMD5Str = reader.readLine();
//                            if (!UmsUtil.verify(retMD5Str.getBytes("UTF-8"), UmsUtil.hexString2ByteArr(chkMD5Str), countPubKey)) {
//                                log.error("回盘文件校验异常，ret文件md5：{}，chk文件md5：{}", retMD5Str, chkMD5Str);
//                                continue;
//                            }
//                            log.info("回盘文件校验通过！chk文件：{}", chkFile.getFilename());
//                            // 将文件上传的远程服务器
//                            InputStream readInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
//
//                            Object[][] dataFromInputStream = TxtUtil.getDataFromInputStream(readInputStream, "UTF-8");
//                            FilerUploadResult filerUploadResult = uploadFile2Cos(file.getFilename(), readInputStream, fileUpload);
//                            lastUpdateFilePaths.add(new DownloadFileBo(dataFromInputStream, file.getFilename(), filerUploadResult));
//
//                            inputStream.close();
//                            chkFileInputStream.close();
//                            byteArrayOutputStream.close();
//                            retInputStream.close();
//                            readInputStream.close();
//                        }
//                    }
//                }
//            }
//            if (CollectionUtils.isEmpty(lastUpdateFilePaths)) {
//                log.info("未查询到需要处理的回盘文件，日期：{}", settleDate.format(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss")));
//                return lastUpdateFilePaths;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.error("下载回盘文件异常：{}", e.getMessage());
//        } finally {
//            if (sftp != null && sftp.isConnected()) {
//                try {
//                    Session Session = sftp.getSession();
//                    Session.disconnect();
//                } catch (JSchException e) {
//                    log.error("download disconnect error: " + e);
//                }
//                sftp.disconnect();
//            }
//        }
//        return lastUpdateFilePaths;
//    }
//
//    /**
//     * 上传文件到远程文件服务器
//     *
//     * @param fileName
//     */
//    private static FilerUploadResult uploadFile2Cos(String fileName, InputStream inputStream, FileUpload fileUpload) {
//        FilerUploadResult upload = null;
//        try {
//            FileItem fileItem = createFileItem(inputStream, fileName);
//            /*//CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
//            CommonsMultipartFile multipartFile = new CommonsMultipartFile(fileItem);
//            upload = fileUpload.upload(multipartFile, "AUTH_READ", null, "OWNER_WRITE").getData();*/
//
//            return upload;
//        } catch (Exception e) {
//            log.info("上传文件到服务器异常，文件名称：{}", fileName);
//        }
//        return upload;
//    }
//
//    /**
//     * FileItem类对象创建
//     *
//     * @param inputStream inputStream
//     * @param fileName    fileName
//     * @return FileItem
//     */
//    public static FileItem createFileItem(InputStream inputStream, String fileName) {
//        FileItemFactory factory = new DiskFileItemFactory(16, null);
//        String textFieldName = "file";
//        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
//        int bytesRead = 0;
//        byte[] buffer = new byte[8192];
//        OutputStream os = null;
//        //使用输出流输出输入流的字节
//        try {
//            os = item.getOutputStream();
//            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
//                os.write(buffer, 0, bytesRead);
//            }
//            inputStream.close();
//        } catch (IOException e) {
//            log.error("Stream copy exception", e);
//            throw new IllegalArgumentException("文件上传失败");
//        } finally {
//            if (os != null) {
//                try {
//                    os.close();
//                } catch (IOException e) {
//                    log.error("Stream close exception", e);
//
//                }
//            }
//            if (inputStream != null) {
//                try {
//                    inputStream.close();
//                } catch (IOException e) {
//                    log.error("Stream close exception", e);
//                }
//            }
//        }
//
//        return item;
//    }
//
//    /**
//     * 获取文件内容
//     *
//     * @param files      文件信息【文件保存地址，文件名称】
//     * @param filePrefix 文件名称前缀
//     * @return {@link List<FileRetBo>}
//     */
//    public static List<FileRetBo> readLocalFiles(Set<String[]> files, String filePrefix) {
//        List<FileRetBo> fileRetBos = new ArrayList<>();
//        if (StringUtils.isEmpty(filePrefix)) {
//            files.forEach(strings -> {
//                Object[][] data = TxtUtil.getData(strings[1], "UTF-8");
//                FileRetBo fileRetBo = new FileRetBo(strings[1], data, null);
//                fileRetBos.add(fileRetBo);
//            });
//        } else {
//            files.stream().filter(ls -> ls[1].startsWith(filePrefix)).forEach(strings -> {
//                Object[][] data = TxtUtil.getData(strings[1], "UTF-8");
//                FileRetBo fileRetBo = new FileRetBo(strings[1], data, null);
//                fileRetBos.add(fileRetBo);
//            });
//        }
//        return fileRetBos;
//    }
//
//    /**
//     * 获取文件内容
//     *
//     * @param files      文件信息【文件保存地址，文件名称】
//     * @param filePrefix 文件名称前缀
//     * @return {@link List<FileRetBo>}
//     */
//    public static List<FileRetBo> readRemoteFiles(List<DownloadFileBo> files, String filePrefix) {
//        List<FileRetBo> fileRetBos = new ArrayList<>();
//
//        if (CollectionUtils.isEmpty(files)) {
//            return fileRetBos;
//        }
//        for (DownloadFileBo file : files) {
//            Object[][] data = file.getFileInfo();
//            FileRetBo fileRetBo = new FileRetBo(file.getFileName(), data, file.getUpload().getUrl());
//            fileRetBos.add(fileRetBo);
//        }
//        return fileRetBos;
//    }
//}
